package org.example.controller;

import com.alibaba.fastjson.JSONObject;
import de.felixroske.jfxsupport.FXMLController;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.util.Callback;
import org.example.Main;
import org.example.config.FileName;
import org.example.model.ApplicationProcess;
import org.example.model.Plan;
import org.example.service.*;
import org.example.utils.AlertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import sun.awt.shell.ShellFolder;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: wwy
 * @Date: 2020/11/26 10:58
 */

@FXMLController
public class JavaProcessManagementController implements Initializable {
    public static Stage dialogStage;
    @Autowired
    private StartApplicationService startApplicationService;
    @Autowired
    private CloseApplicationService closeApplicationService;
    @Autowired
    private ApplicationProcessService applicationProcessService;
    @Autowired
    private PlanService planService;
    @FXML
    private TableView<Plan> planTableView;
    @FXML
    private TableView<ApplicationProcess> applicationProcessTableView;
    @FXML
    private ImageView appImageView;
    private ObservableList<Plan> planData = FXCollections.observableArrayList();
    public static Map<String,ObservableList<ApplicationProcess>> applicationDataMap = new HashMap<>();
    private Plan plan;

    private ApplicationProcess applicationProcess;
    /**
     * 当前修改的值
     */
    private Plan editPlan;
    /**
     * 当前修改的值
     */
    private ApplicationProcess editApplicationProcess;
    /**
     * 当前选中的plan
     */
    private Plan currentPlan;
    /**
     * 当前选中的applicationProcess
     */
    private ApplicationProcess currentApplicationProcess;

    private PlanAddDialogController planAddDialogController = new PlanAddDialogController();

    private AppProcessAddDialogController appProcessAddDialogController = new AppProcessAddDialogController();
    @FXML
    private TableColumn<Plan, String> planNameColumn;
    @FXML
    private TableColumn<Plan, String> priorityColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> appNameColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> appAddressColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> pidColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> statusNameColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> defaultNameColumn;
    @FXML
    private TableColumn<ApplicationProcess,String> listenPortColumn;
    @FXML
    private Label planNameLabel;
    @FXML
    private Label appNameLabel;
    @FXML
    private Label timerLabel;
    @Autowired
    private FileHandleService fileHandleService;
    public static ThreadPoolExecutor executorService = new ThreadPoolExecutor(4,4,1000, TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        //设置每列属性赋值位置
        planNameColumn.setCellValueFactory(cellData -> cellData.getValue().planNameProperty());
        priorityColumn.setCellValueFactory(cellData -> cellData.getValue().priorityProperty());

        //设置每列属性值位置
        appNameColumn.setCellValueFactory(cellData -> cellData.getValue().appNameProperty());
        appAddressColumn.setCellValueFactory(cellData -> cellData.getValue().appAddressProperty());
        pidColumn.setCellValueFactory(cellData -> cellData.getValue().pidProperty());
        statusNameColumn.setCellValueFactory(cellData -> cellData.getValue().statusNameProperty());
        defaultNameColumn.setCellValueFactory(cellData -> cellData.getValue().defaultNameProperty());
        listenPortColumn.setCellValueFactory(cellData -> cellData.getValue().listenPortProperty());
        //初始化表格数据
        planTableView.setItems(planData);

        // Listen for selection changes and show the person details when changed.
        planTableView.getSelectionModel().selectedItemProperty().addListener(
                (observable, oldValue, newValue) -> showPlan(newValue));

        applicationProcessTableView.getSelectionModel().selectedItemProperty().addListener(
                (observable, oldValue, newValue) -> showApplicationProcess(newValue));
    }


    /**
     * 删除
     */
    @FXML
    private void handleDelete(){
        System.out.println("删除方法执行");
        int selectedIndex = applicationProcessTableView.getSelectionModel().getSelectedIndex();
        if(selectedIndex !=-1){
            if(f_alert_confirmDialog("提示","确定删除该应用信息吗，不会关闭已开启的应用")){
                applicationProcessService.delete(currentApplicationProcess.getId());
                applicationProcessTableView.getItems().remove(selectedIndex);
            }


        }else{
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("No Selection");
            alert.setHeaderText("No Person Selected");
            alert.setContentText("Please select a person in the table.");
            alert.showAndWait();
        }

    }

    /**
     * 新增
     */
    @FXML
    private void handleAdd(){
        boolean b = appProcessAddDialogController.showApplicationAddDialog(currentPlan);
        if(b){
            ObservableList<ApplicationProcess> applicationProcessData = applicationDataMap.get(currentPlan.getId() + "");
            if(applicationProcessData == null){
                applicationProcessData = FXCollections.observableArrayList();
                applicationDataMap.put(currentPlan.getId() + "",applicationProcessData);
            }
            applicationProcessData.add(applicationProcess);
            applicationProcessTableView.setItems(applicationProcessData);
            //全局保存状态设置为false
            AppProcessAddDialogController.flag = false;
        }
        System.out.println("添加方法执行");
    }

    /**
     * 修改
     */
    @FXML
    private void handleEdit(){
        boolean b = appProcessAddDialogController.showPlanEditDialog(currentPlan, currentApplicationProcess);
        if(b){
            int currentIndex = -1;
            ObservableList<ApplicationProcess> applicationProcessesData = applicationDataMap.get(currentPlan.getId() + "");
            for (int i = 0; i < applicationProcessesData.size(); i++) {
                if(applicationProcessesData.get(i).getId() == editApplicationProcess.getId()){
                    currentIndex = i;
                }
            }
            if(currentIndex !=-1){
                applicationProcessesData.set(currentIndex,editApplicationProcess);
            }
            //操作表格
            applicationProcessTableView.setItems(applicationProcessesData);
        }
        System.out.println("修改方法执行");
    }

    /**
     * 启动
     */
    @FXML
    private void handleStart(){
        Loading loading = new Loading(Main.getStage());
        loading.show();
        System.out.println("启动方法执行");
        int start = startApplicationService.start(currentApplicationProcess);
        loading.closeStage();
        if(start == 1){
            //映像已经启动
            AlertUtils.sendAlert("提示","软件启动失败","软件已经启动，请关闭后重试");
        }else if(start == 0){
            //启动成功
            AlertUtils.sendAlert("提示","启动成功","启动成功");
        }else if(start == 2){
            //启动失败
            AlertUtils.sendAlert("错误","系统错误","启动失败，请检查文件路径与名称");
        }

    }

    /**
     * 关闭
     */
    @FXML
    private void handleStop(){
        System.out.println("关闭方法执行");
        Loading loading = new Loading(Main.getStage());
        loading.show();
        System.out.println("启动方法执行");
        int close = closeApplicationService.close(currentApplicationProcess);
        loading.closeStage();
        if(close == 1){
            //关闭失败
            AlertUtils.sendAlert("错误","软件关闭失败","软件关闭失败，请关闭后重试");
        }else if(close == 0){
            //关闭成功
            AlertUtils.sendAlert("提示","系统提示","关闭成功");
        }else if(close == 2){
            //启动失败
            AlertUtils.sendAlert("错误","系统错误","启动失败，请检查文件路径与名称");
        }
    }

    /**
     * 开启全部
     */
    @FXML
    private void handleStartAll(){
        System.out.println("开启全部方法执行");
        Loading loading = new Loading(Main.getStage());
        loading.show();
        executorService.execute(()->{
            int i = startApplicationService.startAll(loading);
            loading.closeStage();
            /*Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("提示");
            alert.setHeaderText("启动完成");
            alert.setContentText("请等待程序加载完成");
            alert.showAndWait();*/
        });



    }

    /**
     * 关闭全部
     */
    @FXML
    private void handleStopAll(){
        System.out.println("关闭全部方法执行");
        Loading loading = new Loading(Main.getStage());
        loading.show();
        executorService.execute(()->{
            int i = closeApplicationService.closeAll(loading);
            loading.closeStage();
            /*Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("提示");
            alert.setHeaderText("关闭完成");
            alert.setContentText("请等待程序关闭完成");
            alert.showAndWait();*/
        });

    }

    /**
     * 新增计划
     */
    @FXML
    private void handleAddPlan(){
        boolean b = planAddDialogController.showPlanAddDialog();
        if(b){
            System.out.println("关闭了弹窗");
            //操作表格
            planData.add(plan);
            planTableView.setItems(planData);
            PlanAddDialogController.flag = false;
        }
    }

    /**
     * 修改计划
     */
    @FXML
    private void handleEditPlan(){
        boolean b = planAddDialogController.showPlanEditDialog(currentPlan);
        if(b){
            System.out.println("关闭了弹窗");
            int currentIndex = -1;
            for (int i = 0; i < planData.size(); i++) {
                if(planData.get(i).getId() == editPlan.getId()){
                    currentIndex = i;
                }
            }
            if(currentIndex !=-1){
                planData.set(currentIndex,editPlan);
            }
            //操作表格
            planTableView.setItems(planData);
        }
    }

    /**
     * 删除计划
     */
    @FXML
    private void handleDeletePlan(){
        int selectedIndex = planTableView.getSelectionModel().getSelectedIndex();
        if (selectedIndex >= 0) {
            if(f_alert_confirmDialog("提示","删除计划,将会清空该计划内的软件记录,不会关闭已开启的软件")){
                //删除磁盘文件
                planService.delete(currentPlan.getId());
                planTableView.getItems().remove(selectedIndex);
            }

        } else {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("No Selection");
            alert.setHeaderText("No Person Selected");
            alert.setContentText("Please select a person in the table.");
            alert.showAndWait();
        }
    }

    /**
     * 弹出一个通用的确定对话框
     * @param p_header 对话框的信息标题
     * @param p_message 对话框的信息
     * @return 用户点击了是或否
     */
    public boolean f_alert_confirmDialog(String p_header,String p_message){
        //按钮部分可以使用预设的也可以像这样自己 new 一个
        Alert _alert = new Alert(Alert.AlertType.CONFIRMATION,p_message,new ButtonType("取消", ButtonBar.ButtonData.NO),
                new ButtonType("确定", ButtonBar.ButtonData.YES));
        //设置窗口的标题
        _alert.setTitle("确认");
        _alert.setHeaderText(p_header);
        // showAndWait() 将在对话框消失以前不会执行之后的代码
        Optional<ButtonType> _buttonType = _alert.showAndWait();
        //根据点击结果返回
        if(_buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)){
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * 表格改变
     * 展示计划头名称
     * 展示右边内容
     * @param plan
     */
    private void showPlan(Plan plan){
        if(plan == null){
            return;
        }
        planNameLabel.setText(plan.getPlanName());
        currentPlan = plan;

        ObservableList<ApplicationProcess> applicationProcessesData = applicationDataMap.get(plan.getId() + "");
        //不等于空进行赋值展示
        if(applicationProcessesData != null){
            applicationProcessTableView.setItems(applicationProcessesData);
        }else{
            applicationProcessTableView.setItems(FXCollections.observableArrayList());
        }


    }

    /**
     * 表格改变
     * @param applicationProcess
     */
    private void showApplicationProcess(ApplicationProcess applicationProcess){
        if(applicationProcess == null){
            return;
        }
        appNameLabel.setText(applicationProcess.getAppName());
        if(applicationProcess == null){
            return;
        }
        this.currentApplicationProcess = applicationProcess;
        //展示软件图标
        try {
            String appAddress = applicationProcess.getAppAddress();
            File file = new File(appAddress);
            ShellFolder shellFolder = ShellFolder.getShellFolder(file);
            ImageIcon icon = new ImageIcon(shellFolder.getIcon(true));
            BufferedImage imgIcon = (BufferedImage) icon.getImage();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            // 调整icon图标大小，放大后会模糊
            //imgIcon = resize(imgIcon,64,64);
            boolean png = ImageIO.write(imgIcon, "png", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            Image image = new Image(input);
            appImageView.setImage(image);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void showTimerLabel(String text){
        if(timerLabel !=null){
            timerLabel.setText(text);
        }

    }

    public Plan getPlan() {
        return plan;
    }

    public void setPlan(Plan plan) {
        this.plan = plan;
    }

    public ObservableList<Plan> getPlanData() {
        return planData;
    }

    public void setPlanData(ObservableList<Plan> planData) {
        this.planData = planData;
    }

    public TableView<Plan> getPlanTableView() {
        return planTableView;
    }

    public void setPlanTableView(TableView<Plan> planTableView) {
        this.planTableView = planTableView;
    }

    public Plan getEditPlan() {
        return editPlan;
    }

    public void setEditPlan(Plan editPlan) {
        this.editPlan = editPlan;
    }

    public ApplicationProcess getApplicationProcess() {
        return applicationProcess;
    }

    public void setApplicationProcess(ApplicationProcess applicationProcess) {
        this.applicationProcess = applicationProcess;
    }

    public Map<String, ObservableList<ApplicationProcess>> getApplicationDataMap() {
        return applicationDataMap;
    }

    public void setApplicationDataMap(Map<String, ObservableList<ApplicationProcess>> applicationDataMap) {
        applicationDataMap = applicationDataMap;
    }

    public ApplicationProcess getEditApplicationProcess() {
        return editApplicationProcess;
    }

    public void setEditApplicationProcess(ApplicationProcess editApplicationProcess) {
        this.editApplicationProcess = editApplicationProcess;
    }


}
